
package com.zxl.grocery.microservice.auth.client.jwt;

import com.zxl.grocery.microservice.auth.client.config.ServiceAuthConfig;
import com.zxl.grocery.microservice.auth.client.feign.ServiceAuthFeign;
import com.zxl.grocery.microservice.auth.common.event.AuthRemoteEvent;
import com.zxl.grocery.microservice.auth.common.util.jwt.IJWTInfo;
import com.zxl.grocery.microservice.auth.common.util.jwt.JWTHelper;
import com.zxl.grocery.microservice.common.exception.auth.ClientTokenException;
import com.zxl.grocery.microservice.common.msg.BaseResponse;
import com.zxl.grocery.microservice.common.msg.ObjectRestResponse;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.List;

/**
 * Created by zxl on 2017/10/13 0013.
 */
@Configuration
@Slf4j
@EnableScheduling
public class ServiceAuthUtil implements ApplicationListener<AuthRemoteEvent> {
    @Autowired
    private ServiceAuthConfig serviceAuthConfig;
    @Autowired
    private ServiceAuthFeign serviceAuthFeign;
    private List<String> allowedClient;
    private String clientToken;

    /**
     * @Author: Lzx
     * @Description: 获取token中的信息
     * @Params:  * @param null
     * @Date: 22:52 2017/10/24
     */
    public IJWTInfo getInfoFromToken(String token) throws Exception {
        try {
            return JWTHelper.getInfoFromToken(token, serviceAuthConfig.getPubKeyByte());//获取token中的信息
        } catch (ExpiredJwtException ex) {
            throw new ClientTokenException("Client token expired!");
        } catch (SignatureException ex) {
            throw new ClientTokenException("Client token signature error!");
        } catch (IllegalArgumentException ex) {
            throw new ClientTokenException("Client token is null or empty!");
        }
    }

    /**
     * @Author: Lzx
     * @Description: 每5分钟请求一次 获取该服务允许访问的客户端列表
     * @Params:  * @param null
     * @Date: 22:22 2017/10/24
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void refreshAllowedClient() {
        log.debug("refresh allowedClient.....");
        //先转基础对象，判断是否请求成功
        BaseResponse resp = serviceAuthFeign.getAllowedClient(serviceAuthConfig.getClientId(), serviceAuthConfig.getClientSecret());//远程调用鉴权服务，获取允许访问的客户端列表
        if (resp.getStatus() == 200) {//判断请求是否成功
            //再转高阶对象
            ObjectRestResponse<List<String>> allowedClient = (ObjectRestResponse<List<String>>) resp;
            this.allowedClient = allowedClient.getData();//获取允许访问的客户端列表
        }
    }

    /**
     * @Author: Lzx
     * @Description: 每3分钟请求一次 获取该服务的token
     * @Params:  * @param null
     * @Date: 22:22 2017/10/24
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    public void refreshClientToken() {
//        try {
//            log.info("refresh client token.....");
//            this.getInfoFromToken(this.clientToken);//判断该服务的token是否过期
//        } catch (Exception e) {
//            BaseResponse resp = serviceAuthFeign.getAccessToken(serviceAuthConfig.getClientId(), serviceAuthConfig.getClientSecret());//向鉴权系统请求新的token
//            if (resp.getStatus() == 200) {
//                ObjectRestResponse<String> clientToken = (ObjectRestResponse<String>) resp;
//                this.clientToken = clientToken.getData();
//            }
        log.debug("refresh client token.....");
        BaseResponse resp = serviceAuthFeign.getAccessToken(serviceAuthConfig.getClientId(), serviceAuthConfig.getClientSecret());
        if (resp.getStatus() == 200) {
            ObjectRestResponse<String> clientToken = (ObjectRestResponse<String>) resp;
            this.clientToken = clientToken.getData();
        }
    }

    /**
     * @Author: Lzx
     * @Description: 获取客户端token
     * @Params:  * @param null
     * @Date: 22:49 2017/10/24
     */
    public String getClientToken() {
        if (this.clientToken == null) {
            this.refreshClientToken();
        }
        return clientToken;
    }
    /**
     * @Author: Lzx
     * @Description: 获取该服务允许访问的服务列表
     * @Params:  * @param null
     * @Date: 22:21 2017/10/24
     */
    public List<String> getAllowedClient() {
        if (this.allowedClient == null) {
            this.refreshAllowedClient();
        }
        return allowedClient;
    }

    @Override
    public void onApplicationEvent(AuthRemoteEvent authRemoteEvent){
        this.allowedClient = authRemoteEvent.getAllowedClient();
    }
}